#include "StdAfx.h"
#include "UVDispObject.h"

UVDispObject::UVDispObject(void)
{
	totalTime = 0;
}

UVDispObject::~UVDispObject(void)
{
}

int UVDispObject::Load( char* tex_tga, char* disp_tga, char* mask_tga, char* model_nfg)
{
	if (model.Load(model_nfg) == LOAD_FAILED)
		return LOAD_FAILED;

	const char* tga[3] = {tex_tga, disp_tga, mask_tga};
	glGenTextures(3, tex_id);
	for (int i = 0; i < 3; ++i)
	{
		int height, width, bpp;
		glBindTexture(GL_TEXTURE_2D, tex_id[i]);
		char* imgData = LoadTGA(tga[i], &width, &height, &bpp);
		//
		if (bpp == 24)
			//RGB
			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, imgData);
		else
			//RGBA
			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imgData);
		////filter for minification
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		////filter for magnification
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);

		if (i == 1)
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
		else
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

		delete[] imgData;
	}

	
	glBindTexture(GL_TEXTURE_2D, 0);
	// Buffer vertices
	glGenBuffers(1, &vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glBufferData(GL_ARRAY_BUFFER, model.num_vertices * sizeof(Vertex), model.vertices, GL_STATIC_DRAW);
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	//

	glGenBuffers(1, &ibo);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, model.num_indices * sizeof(GLushort), model.indices, GL_STATIC_DRAW);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

	myShaders.Init("../Resources/Shaders/UVDisplacementShaderVS.vs",
					"../Resources/Shaders/UVDisplacementShaderFS.fs");

	
	myShaders.getUniformLocation("u_time", time_unf_loc);
	myShaders.getUniformLocation("u_texture", tex_attr_loc[0]);
	myShaders.getUniformLocation("u_displace", tex_attr_loc[1]);
	myShaders.getUniformLocation("u_mask", tex_attr_loc[2]);
	return LOAD_SUCCEEDED;
}

void UVDispObject::Draw( ESContext *esContext, Camera* camera)
{
	glUseProgram(myShaders.program);
	// Open buffer
	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);

	// Bind Vertex to Shaders
	glEnableVertexAttribArray(myShaders.positionAttribute);
	glVertexAttribPointer(myShaders.positionAttribute, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
	glEnableVertexAttribArray(myShaders.uvAttribute);
	glVertexAttribPointer(myShaders.uvAttribute, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (char*)0 + sizeof(Vector3) + sizeof(Vector4));

	// Bind Texture
	for (int i = 0; i < 3; ++i)
	{
		glActiveTexture(GL_TEXTURE0 + i);
		glBindTexture(GL_TEXTURE_2D, tex_id[i]);
		glUniform1i(tex_attr_loc[i], i);
	}

	// Bind MVP Matrix
	Matrix mvp =  getWorldMatrix() * camera->getViewMatrix() * camera->getProjectionMatrix();
	glUniformMatrix4fv(myShaders.matMVPUniform, 1, GL_FALSE, &(mvp.m[0][0]));

	// Bind Index
	int size;
	glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);

	// Bind time
	glUniform1f(time_unf_loc, totalTime);

	// Draw
	glDrawElements(GL_TRIANGLES, size / sizeof(GLushort), GL_UNSIGNED_SHORT, 0);

	// Release buffer
	glBindTexture(GL_TEXTURE_2D, 0);
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}


void UVDispObject::Update ( ESContext *esContext, float deltaTime)
{
	totalTime += deltaTime;
}
